package com.ricky.chat.client.server;

import com.ricky.chat.common.coder.JsonMsgDecoder;
import com.ricky.chat.common.coder.JsonMsgEncoder;
import com.ricky.chat.client.dialog.ChatWindow;
import com.ricky.chat.client.handler.ClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;

/**
 * @Auther：ricky
 * @Date: 2023-08-02 10:46
 * @Description
 */
public class RickyClient {
    private final static Logger LOGGER = LoggerFactory.getLogger(RickyClient.class);
    public static final String SERVER_IP = "127.0.0.1";
    public static final int SERVER_PORT = 8001;

    /**
     * 连接服务器并返回Channel
     * @return Channel 连接通道
     */
    public static Channel connectAndGetChannel() throws InterruptedException {
        Bootstrap b = new Bootstrap();
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            b.group(workGroup);
            b.channel(NioSocketChannel.class);
            b.remoteAddress(SERVER_IP, SERVER_PORT);
            b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
            b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
            b.option(ChannelOption.SO_KEEPALIVE, true);
            b.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    // 添加解码器（与服务端对应）
                    socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));
                    socketChannel.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
                    socketChannel.pipeline().addLast(new JsonMsgDecoder()); // 添加解码器
                    // 保留原有的编码器
                    socketChannel.pipeline().addLast(new LengthFieldPrepender(4, false));
                    socketChannel.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
                    socketChannel.pipeline().addLast(new JsonMsgEncoder());
                    socketChannel.pipeline().addLast(new ClientHandler());
                }
            });
            ChannelFuture channelFuture = b.connect();
            channelFuture.sync();
            return channelFuture.channel();
        } catch (Exception ex) {
            workGroup.shutdownGracefully();
            throw ex;
        }
    }

    /**
     * 启动GUI聊天客户端
     */
    public static void startGuiClient() {
        SwingUtilities.invokeLater(() -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                LOGGER.warn("无法设置系统外观", e);
            }

            ChatWindow chatWindow = new ChatWindow();
            chatWindow.setVisible(true);
        });
    }

    public static void main(String[] args) {
        startGuiClient();
    }
}